home *** CD-ROM | disk | FTP | other *** search
- COMMENT ~
- GRAPHICS.ASM -- Graphic Plotting Procedures
-
- From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
- by Christopher L. Morgan
- Copyright (C) 1984 by The Waite Group, Inc.
-
- Contents:
- ---------
- CLS -- Clear the screen
- GET_COLOR -- Get the color of a point on the med res color screen
- GMSG_OUT -- Plot a string
- PAINT -- Fill an area with specified color
- RCHAR -- Plot a raster character
- SCHAR -- Plot a stroke character
- SET_BOX -- Fill a rectangular box with specified color
- SET_LIN -- Draw a line
- SET_PT -- Plot a point
- XOR_BOX -- Fill a rectangular box using XOR
- XOR_PT -- Plot a point using XOR
-
- >>>>> See GRAPHICS.DOC for complete descriptions of these routines. <<<<<
- ------------------------------------------------------------------------------
- These variables need to be defined in the source code calling the GRAPHICS
- routines. See GRAPHICS.DOC. ~
- EXTRN CBYTES:BYTE, COLOR:WORD, DELDE:WORD, DELDX:WORD
- EXTRN DELDY:WORD, DELP:WORD, DELS:WORD, DELSE:WORD
- EXTRN DELSX:WORD, DELSY:WORD, FONT:BYTE, PAINT_STAK:WORD
- EXTRN X0:WORD, X1:WORD, X2:WORD, XMAGN:BYTE
- EXTRN XMSG:WORD, Y0:WORD, Y1:WORD, Y2:WORD
- EXTRN YMAGN:BYTE, YMSG:WORD
- ;______________________________________________________________________________
- ;These tables would be better included in the source code calling the
- ; GRAPHICS routines, and then commented out here. See GRAPHICS.DOC
- ;
- DATAS SEGMENT PUBLIC
- CTABLE DW 0003FH,0403FH,0803FH,0C03FH
- DW 000CFH,010CFH,020CFH,030CFH
- DW 000F3H,004F3H,008F3H,00CF3H
- DW 000FCH,001FCH,002FCH,003FCH
-
- PTABLE DW 32 DUP(?) ;A dummy (See GRAPHICS.DOC)
-
- XTABLE DW 0FFC0H,0FFF0H,0FFFCH,0FFFFH
- DW 03FC0H,03FF0H,03FFCH,03FFFH
- DW 00FC0H,00FF0H,00FFCH,00FFFH
- DW 003C0H,003F0H,003FCH,003FFH
- DATAS ENDS
- ;______________________________________________________________________________
- ;
- CODES SEGMENT
- PUBLIC CLS,SET_PT,XOR_PT,GET_COLOR,SET_BOX,XOR_BOX
- PUBLIC SET_LIN,SCHAR,RCHAR,GMSG_OUT,PAINT
- ASSUME CS:CODES,DS:DATAS
- ;____________________________I/O ROUTINES______________________________________
- ;Routine to clear the graphics screen
- ;
- CLS PROC FAR
- PUSH CX ;Save registers
- PUSH AX
- ;
- ;Set up the registers
- MOV CX,2000H ;Word count of whole screen
- MOV AX,0 ;Zero pattern for the screen
- MOV DI,AX ;Set starting address
- CLD ;Go in forward direction
- ;
- ;Clear the screen with a single string operation
- REP STOSW ;This clears the screen
- ;
- POP AX ;Restore registers
- POP CX
- RET
- CLS ENDP
- ;------------------------------------------------------------------------------
- ;Routine to plot a point on medium resolution color screen
- ;
- SET_PT PROC FAR
- PUSH BX ;Save registers
- PUSH SI
- PUSH AX
- ;
- ;Multiply Y-coord by bytes/row & adjust for even/odd lines
- MOV AX,DI ;Get Y-coordinate into part
- MOV AH,AL ; and into high part
- AND AX,01FEH ;Mask off unwanted parts
- SAL AX,1 ;Times 4
- SAL AX,1 ;Times 8
- SAL AX,1 ;Times 16
- MOV BX,AX ;Goes into address
- AND BH,7 ; without adjustment
- SAL AX,1 ;Times 32
- SAL AX,1 ;Times 64
- ADD BX,AX ;Addr gets Y-coord times 80
- ;
- ;Add X-coordinate to address
- MOV AX,SI ;Get X-coordinate
- SAR AX,1 ;Divide
- SAR AX,1 ; by 4
- ADD BX,AX ;Here is the address
- ;
- ;Compute the rotated mask and color
- AND SI,3 ;Just pixel position into index
- SAL SI,1 ;Index times 2
- SAL SI,1 ;Index times 4
- ADD SI,DX ;4 * pixel position + color
- SAL SI,1 ;8 * pixel position + 2 * color
- MOV AX,CTABLE[SI] ;Look up rotated color & mask
- ;
- ;Insert the color into the video byte
- AND AL,ES:[BX] ;Get old byte & remove old pixel
- OR AL,AH ;Insert new color
- MOV ES:[BX],AL ;Put the byte back
- ;
- POP AX ;Restore registers
- POP SI
- POP BX
- RET
- SET_PT ENDP
- ;------------------------------------------------------------------------------
- ;Routine to XOR a point onto medium resolution color screen
- ;
- XOR_PT PROC FAR
- PUSH BX ;Save registers
- PUSH SI
- PUSH AX
- ;
- ;Multiply Y-coord by bytes/row & adjust for even/odd lines
- MOV AX,DI ;Get Y-coordinate into part
- MOV AH,AL ; and into high part
- AND AX,01FEH ;Mask off unwanted parts
- SAL AX,1 ;Times 4
- SAL AX,1 ;Times 8
- SAL AX,1 ;Times 16
- MOV BX,AX ;Goes into address
- AND BH,7 ; without adjustment
- SAL AX,1 ;Times 32
- SAL AX,1 ;Times 64
- ADD BX,AX ;Addr gets Y-coord times 80
- ;
- ;Add X-coordinate to address
- MOV AX,SI ;Get X-coordinate
- SAR AX,1 ;Divide
- SAR AX,1 ; by 4
- ADD BX,AX ;Here is the address
- ;
- ;Compute the mask for color and use it
- AND SI,3 ;Just the bit count into index
- SAL SI,1 ;Index times 2
- SAL SI,1 ;Index times 4
- ADD SI,DX ;4 * pixel position + color
- SAL SI,1 ;8 * pixel position + 2 * color
- MOV AX,CTABLE[SI] ;Look up rotated color & mask
- XOR ES:[BX],AH ;XOR the byte with the color
- ;
- POP AX ;Restore registers
- POP SI
- POP BX
- RET
- XOR_PT ENDP
- ;------------------------------------------------------------------------------
- ;Routine to return color of a point on med res color screen
- ;
- GET_COLOR PROC FAR
- PUSH BX ;Save registers
- PUSH CX
- ;
- ;Multiply Y-coord by bytes/row & adjust for even/odd lines
- MOV AX,DI ;Get Y-coordinate into part
- MOV AH,AL ; and into high part
- AND AX,01FEH ;Mask off unwanted parts
- SAL AX,1 ;Times 4
- SAL AX,1 ;Times 8
- SAL AX,1 ;Times 16
- MOV BX,AX ;Goes into address
- AND BH,7 ; without adjustment
- SAL AX,1 ;Times 32
- SAL AX,1 ;Times 64
- ADD BX,AX ;Addr gets Y-coord times 80
- ;
- ;Add X-coordinate to address
- MOV AX,SI ;Get X-coordinate
- SAR AX,1 ;Divide
- SAR AX,1 ; by 4
- ADD BX,AX ;Here is the address
- ;
- ;Compute the position of the pixel in the byte
- MOV CX,SI ;Use X-coord to determine count
- AND CX,3 ;Just the bit count
- INC CX ; plus one
- SAL CX,1 ;2 bits/pixel
- ;
- ;Get the byte and rotate into place
- MOV AL,ES:[BX] ;Get old byte
- ROL AL,CL ;Rotate left this many times
- AND AX,3 ;Just the pixel color
- ;
- POP CX ;Restore registers
- POP BX
- RET
- GET_COLOR ENDP
- ;------------------------------------------------------------------------------
- ;Routine to set & fill a rectangular box
- ;
- SET_BOX PROC FAR
- PUSH SI ;Save registers
- PUSH DI
- PUSH DX
- PUSH BX
- PUSH CX
- PUSH AX
- ;
- ;Determine byte position for start
- ;
- ;Get Y contribution
- MOV AX,Y1 ;Get starting Y-coordinate
- MOV AH,AL ;Replicate for odd/even bank
- AND AX,01FEH ;Mask off unwanted parts
- SAL AX,1 ;Times 4
- SAL AX,1 ;Times 8
- SAL AX,1 ;Times 16
- MOV DI,AX ;Addr gets Y-coord * 16
- AND DI,7FFH ;Not the odd/even bit
- SAL AX,1 ;Times 32
- SAL AX,1 ;Times 64
- ADD DI,AX ;Addr gets Y-coord * 80
- ;
- ;Add in X contribution
- MOV AX,X1 ;Get X-coordinate
- SAR AX,1 ;Divide
- SAR AX,1 ; by 4
- ADD DI,AX ;Beginning of offset
- ;
- ;Count for outer loop
- MOV CX,Y2 ;Ending Y-coordinate
- SUB CX,Y1 ; minus starting Y-coordinate
- INC CX ; plus one
- ;
- ;Count for inner loop
- MOV SI,X2 ;Ending X-coordinate
- SAR AX,1 ;Divide
- SAR AX,1 ; by 4
- MOV AX,X1 ;Starting X-coordinate
- SAR AX,1 ;Divide
- SAR AX,1 ; by 4
- SUB SI,AX ;Take the difference
-
- ;Get the color
- MOV BX,COLOR ;Get the color
- AND BX,3 ;Just between 0 & 3
- MOV DL,CBYTES[BX] ;Look up color pattern
- ;
- ;Determine mask for start & ending bytes
- MOV BX,X1 ;Starting byte
- AND BX,3 ;Just the pixel position
- SAL BX,1 ;Times 2
- SAL BX,1 ;Times 4
- MOV AX,X2 ;Ending byte
- AND AX,3 ;Just the pixel position
- ADD BX,AX ;4 * starting + ending
- SAL BX,1 ;8 * starting + 2 * ending
- MOV BX,XTABLE[BX] ;Look up the masks
- ;
- ;Set up masked color bytes
- MOV DH,DL ;Color for left bytes
- MOV AH,DL ;Color for middle bytes
- AND DX,BX ;Mask left & right color bytes
- ;
- CLD ;Forward
- SBOXLOOP:
- PUSH CX ;Save count of outer loop
- PUSH DI ;Save initial byte position
- ;
- MOV CX,SI ;Count for inner loop
- ;
- ;Check for only one byte
- MOV AL,BH ;Get the mask
- JCXZ SBOXLOOP2 ;If ending byte coincides
- ;
- ;Color leftmost byte of the scan line
- NOT AL ;Reverse the mask for clearing
- AND AL,ES:[DI] ;Get byte frm mem & clr pixels
- OR AL,DH ;Put color in place
- STOSB ;Put byte in place
- ;
- ;Check for just two bytes
- DEC CX ;Count the byte
- JCXZ SBOXLOOP1 ;Done?
- ;
- ;Color middle bytes of the scan line
- ;
- MOV AL,AH ;Color for middle bytes
- REP STOSB ;Put middle bytes in place
- ;
- ;Handle rightmost byte of the scan line
- ;
- ;Come here if two or more bytes
- SBOXLOOP1:
- MOV AL,0FFH ;Set full mask
- ;
- ;In any case, come here to adjust the masks
- SBOXLOOP2:
- AND AL,BL ;Bring in right part of mask
- AND DL,AL ;Clear left part of color
- ;
- ;Color the byte
- NOT AL ;Reverse the mask for clearing
- AND AL,ES:[DI] ;Get byte from mem & clr pixels
- OR AL,DL ;Put pixels in the byte
- STOSB ;Put byte back into video RAM
- ;
- ;Compute next scan line
- POP DI ;Restor addr of lft side of box
- TEST DI,2000H ;Odd or even line?
- JZ SBOXLOOP3 ;Skip if even
- ADD DI,80 ; else add 80 bytes/line
- SBOXLOOP3:
- XOR DI,2000H ;Change banks in any case
- POP CX ;Restore outer loop count
- LOOP SBOXLOOP ;Next scan line
- ;
- POP AX ;Restore registers
- POP CX
- POP BX
- POP DX
- POP DI
- POP SI
- RET
- SET_BOX ENDP
- ;------------------------------------------------------------------------------
- ;Routine to fill a rectangular box with color using XOR
- ;
- XOR_BOX PROC FAR
- PUSH SI ;Save registers
- PUSH DI
- PUSH DX
- PUSH BX
- PUSH CX
- PUSH AX
- ;
- ;Determine byte position for start
- ;
- ;Get Y contribution
- MOV AX,Y1 ;Get starting Y-coordinate
- MOV AH,AL ;Replicate for odd/even bank
- AND AX,01FEH ;Mask off unwanted parts
- SAL AX,1 ;Times 4
- SAL AX,1 ;Times 8
- SAL AX,1 ;Times 16
- MOV DI,AX ;Addr gets Y-coord * 16
- AND DI,7FFH ;Not the odd/even bit
- SAL AX,1 ;Times 32
- SAL AX,1 ;Times 64
- ADD DI,AX ;Addr gets Y-coord * 80
- ;
- ;Add in X contribution
- MOV AX,X1 ;Get X-coordinate
- SAR AX,1 ;Divide
- SAR AX,1 ; by 4
- ADD DI,AX ;Beginning of offset
- ;
- ;Count for outer loop
- MOV CX,Y2 ;Ending Y-coordinate
- SUB CX,Y1 ; minus starting Y-coordinate
- INC CX ; plus one
- ;
- ;Count for inner loop
- MOV SI,X2 ;Ending X-coordinate
- SAR AX,1 ;Divide
- SAR AX,1 ; by 4
- MOV AX,X1 ;Starting X-coordinate
- SAR AX,1 ;Divide
- SAR AX,1 ; by 4
- SUB SI,AX ;Take the difference
- ;
- ;Get the color
- MOV BX,COLOR ;Get the color
- AND BX,3 ;Just between 0 & 3
- MOV DL,CBYTES[BX] ;Look up color pattern
- ;
- ;Determine mask for start and ending bytes
- MOV BX,X1 ;Starting bytes
- AND BX,3 ;Just the pixel position
- SAL BX,1 ;Times 2
- SAL BX,1 ;Times 4
- MOV AX,X2 ;Ending byte
- AND AX,3 ;Just the pixel position
- ADD BX,AX ;4 * starting + ending
- SAL BX,1 ;8 * starting + 2 * ending
- MOV BX,XTABLE[BX] ;Look up the masks
- ;
- ;Set up masked color bytes
- MOV DH,DL ;Color for left bytes
- MOV AH,DL ;Color for middle bytes
- AND DX,BX ;Mask left & right color bytes
- ;
- CLD ;Forward
- XBOXLOOP:
- PUSH CX ;Save count of outer loop
- PUSH DI ;Save initial byte position
- ;
- MOV CX,SI ;Count for inner loop
- ;
- ;Check if only one byte in a scan line
- MOV AL,BH ;Get the mask
- JCXZ XBOXLOOP3 ;If ending byte coincides
- ;
- ;XOR the leftmost byte
- XOR ES:[DI],DH ;XOR color into memory
- INC DI ;Next byte
- DEC CX ;Count it
- JCXZ XBOXLOOP2 ;Done?
- ;
- ;XOR the middle bytes
- XBOXLOOP1:
- XOR ES:[DI],AH ;XOR color byte into memory
- INC DI ;Next byte
- LOOP XBOXLOOP1 ;Loop to get all the middle
- ;
- ;Handle rightmost byte
- ;
- ;Come here if two or more bytes
- XBOXLOOP2:
- MOV AL,0FFH ;Set full mask
- ;
- ;In any case, come here to adjust the masks
- XBOXLOOP3:
- AND AL,BL ;Bring in right part of mask
- AND DL,AL ;Clear left part of color
- ;
- ;XOR the rightmost byte
- XOR ES:[DI],DL ;XOR byte into memory
- INC DI ;Next byte
- ;
- POP DI ;Restore the leftmost address
- TEST DI,2000H ;Odd or even line?
- JZ XBOXLOOP4 ;Skip if even
- ADD DI,80 ; else add 80 bytes/line
- XBOXLOOP4:
- XOR DI,2000H ;Change banks in any case
- POP CX ;Restore outer loop count
- LOOP XBOXLOOP ;Next scan line
- ;
- POP AX ;Restore registers
- POP CX
- POP BX
- POP DX
- POP DI
- POP SI
- RET
- XOR_BOX ENDP
- ;------------------------------------------------------------------------------
- ;Routine to draw a line
- ;
- SET_LIN PROC FAR
- PUSH BX ;Save registers
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH AX
- ;
- ;Set up X and Y updates
- MOV SI,1 ;Start with positive 1 for
- MOV DI,1 ; X and Y update
- ;
- ;Find |Y2-Y1|
- MOV DX,Y2 ;Get Y2
- SUB DX,Y1 ;Subtract Y1
- JGE STOR_Y ;Skip if Y2-Y1 is not negative
- NEG DI ;Mov in negative Y direction
- NEG DX ;Absolute value of Y2-Y1
- STOR_Y:
- MOV DELDY,DI ;Store Y update for diag moves
- ;
- ;Find |X2-X1|
- MOV CX,X2 ;Get X2
- SUB CX,X1 ;Subtract X1
- JGE STOR_X ;Skip if X2-X1 is not negative
- NEG SI ;Mov in negative X direction
- NEG CX ;Absolute value of X2-X1
- STOR_X:
- MOV DELDX,SI ;Store X update for diag moves
- ;
- ;Sort |Y2-Y1| & |X2-X1|
- CMP CX,DX ;Compare DELS with DELP
- JGE SET_DIAG ;Skip if straight move along X
- MOV SI,0 ;If straight=vert, kill X updat
- XCHG CX,DX ; & exchange differences
- JMP STOR_DELSXY
- SET_DIAG:
- MOV DI,0 ;If straight=horz, kill Y updat
- ;
- ;Store DELS, DELP, DELSX, & DELSY
- STOR_DELSXY:
- MOV DELS,CX ;Change in straight direction
- MOV DELP,DX ;Change in perpndic to straight
- MOV DELSX,SI ;X update in straight direction
- MOV DELSY,DI ;Y update in straight direction
- ;
- ;Get initial values for X & Y
- MOV SI,X1 ;X-coordinate
- MOV DI,Y1 ;Y-coordinate
- ;
- ;Compute initial value & increments for error function
- MOV AX,DELP
- SAL AX,1 ;2 * DELP
- MOV DELSE,AX ;Change if straight move
- ;
- SUB AX,CX ;2 * DELP - DELS
- MOV BX,AX ;Initial value
- ;
- SUB AX,CX ;2 * DELP - 2 * DELS
- MOV DELDE,AX ;Change if diagonal move
- ;
- ;Adjust count
- INC CX
- ;
- ;Set the color
- MOV DX,COLOR ;Get the color
- ;
- ;Main loop structure
- LIN_LOOP:
- CALL SET_PT ;Plot the point
- CMP BX,0 ;Determine straight or
- JGE DIAGONAL ; diagonal move?
- ;
- ;Straight move case
- STRAIGHT:
- ADD SI,DELSX ;Update X
- ADD DI,DELSY ;Update Y
- ADD BX,DELSE ;Update error term
- LOOP LIN_LOOP ;Next point
- JMP LIN_XIT
- ;Diagonal move case
- DIAGONAL:
- ADD SI,DELDX ;Update X
- ADD DI,DELDY ;Update Y
- ADD BX,DELDE ;Update error term
- LOOP LIN_LOOP ;Next point
- LIN_XIT:
- POP AX ;Restore registers
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- RET
- SET_LIN ENDP
- ;------------------------------------------------------------------------------
- ;Routine to plot a stroke character
- ;
- SCHAR PROC FAR
- PUSH SI ;Save registers
- PUSH CX
- PUSH AX
- ;
- CBW ;Make ASCII code into 16-bit
- SAL AX,1 ;Times 2
- MOV SI,AX ;Into the index
- MOV SI,PTABLE[SI] ;Look up the particular char
- MOV AX,X0 ;X-coord of upper left corner
- MOV X2,AX
- MOV AX,Y0 ;Y-coord of upper left corner
- MOV Y2,AX
- ;
- ;Run through the strokes
- NEWSTROKE:
- LODSB ;Get the code byte
- CMP AL,1AH ;End of strokes?
- JZ SCHAR_XIT
- MOV DL,AL ;Save code
- ;
- ;Update X-coordinate of current position
- MOV AX,X2 ;Old X-coordinate
- MOV X1,AX ; gets pushed back
- LODSB ;New X-coordinate
- MOV CL,XMAGN ; times XMAGN
- MUL CL ;Multiply
- ADD AX,X0 ;Add to upper left corner
- MOV X2,AX ; & put into current position
- ;
- ;Update Y-coordinate of current position
- MOV AX,Y2 ;Old Y-coordinate
- MOV Y1,AX ; gets pushed back
- LODSB ;New Y-coordinate
- MOV CL,YMAGN ; times YMAGN
- MUL CL ;Multiply
- ADD AX,Y0 ;Add to upper left corner
- MOV Y2,AX ; & put into current position
- ;
- CMP DL,'U' ;Pen up?
- JE NEWSTROKE ;Skip, if so
- ;
- CALL SET_LIN ;Draw the stroke
- ;
- JMP NEWSTROKE ;Get next stroke
- SCHAR_XIT:
- POP AX ;Restore registers
- POP CX
- POP SI
- RET
- SCHAR ENDP
- ;------------------------------------------------------------------------------
- ;Routine to plot a raster character
- ;
- RCHAR PROC FAR
- PUSH SI ;Save registers
- PUSH DX
- PUSH CX
- PUSH AX
- ;
- ;Look up pattern for character
- CBW ;Make ASCII code into 16-bit
- SAL AX,1 ;Times 2
- SAL AX,1 ;Times 4
- SAL AX,1 ;Times 8
- ADD AX,0FA6EH + 7 ;Character table + pattern end
- MOV SI,AX ;Here is the offset
- ;
- MOV DX,DS ;Save old DS
- MOV AX,0F000H ;Point DS to ROM segment
- MOV DS,AX ;Here is the data segment
- ;
- ;Store the pattern on the stack
- MOV CX,8 ;For a count of 8 bytes
- STD ;Backward direction
- RCHAR1:
- LODSB ;Load
- PUSH AX ;Push onto stack
- LOOP RCHAR1
- ;
- MOV DS,DX ;Restore data segment
- ;
- ;Get the starting point
- MOV AX,X0 ;Get X-coordinate
- MOV X1,AX
- MOV AX,Y0 ;Get Y-coordinate
- MOV Y1,AX
- ;
- MOV CX,8 ;For a count of 8 rows
- RCHAR2:
- POP DX ;Get the next row
- PUSH CX ;Save the count
- ;
- MOV AL,YMAGN ;Vertical sizing
- CBW
- DEC AX ;One less
- ADD AX,Y1 ;Add to new dot position
- MOV Y2,AX
- ;
- MOV CX,8 ;For a count of 8 dots
- RCHAR3:
- PUSH CX ;Save the count
- ;
- MOV AL,XMAGN ;Horizontal sizing
- CBW
- DEC AX ;One less
- ADD AX,X1 ;Add to new dot position
- MOV X2,AX
- ;
- TEST DL,80H ;Check the dot
- JZ RCHAR4 ; & skip if zero
- ;
- CALL SET_BOX ;Plot if a one
- RCHAR4:
- MOV AX,X2 ;Next column
- INC AX ;One over from end of box
- MOV X1,AX ;Into next dot position
- ROL DL,1 ;Next dot from pattern
- POP CX ;Restore count of dots
- LOOP RCHAR3 ;Loop for next dot
- ;
- MOV AX,X0 ;Restore to first column
- MOV X1,AX ;Beginning of row
- MOV AX,Y2 ;Next row
- INC AX ;One down from end of box
- MOV Y1,AX ;Into next row position
- POP CX ;Restore count of rows
- LOOP RCHAR2 ;Loop for next row
- ;
- POP AX ;Restore registers
- POP CX
- POP DX
- POP SI
- RET
- RCHAR ENDP
- ;------------------------------------------------------------------------------
- ;Routine to print a message on the graphics screen
- ;
- GMSG_OUT PROC FAR
- ;
- ;Get (X,Y) location of message on the screen
- MOV AX,XMSG ;Get X-coordinate on screen
- MOV X0,AX ; for first character
- MOV AX,YMSG ;Get Y-coordinate on screen
- MOV Y0,AX ; for first character
- CLD ;Go in forward direction
- ;
- ;Main loop through characters of the message
- GMSG_LOOP:
- CLD ;Forward direction
- LODSB ;Get the ASCII code
- CMP AL,0 ;End of string?
- JE GMSG_XIT
- ;
- ;Check for fonts
- FONT0:
- CMP FONT,0 ;Use font 0?
- JNE FONT1
- CALL SCHAR ;Use stroke characters
- FONT1:
- CMP FONT,1 ;Use font 1?
- JNE NEXTCHAR
- CALL RCHAR ;Use raster characters
- NEXTCHAR:
- MOV AL,8 ;Character cell width
- MOV CL,XMAGN ;Times horizontal magnitude
- MUL CL ;Multiply
- ADD X0,AX ;Add to loc of previous char
- ;
- JMP GMSG_LOOP ;Loop for next character
- GMSG_XIT:
- RET
- GMSG_OUT ENDP
- ;------------------------------------------------------------------------------
- ;Routine to fill an area with a specified color
- ; Uses two subroutines: PUSHPAINT & POPPAINT
- ;
- ;PUSHPAINT pushes X- & Y-coordinates on paint stack
- PUSHPAINT PROC NEAR
- DEC BP ;BP is the paint stack pointer
- DEC BP ; & gets decremented first
- MOV [BP],SI ;Push X
- DEC BP
- DEC BP
- MOV [BP],DI ;Push Y
- RET
- PUSHPAINT ENDP
- ;
- ;POPPAINT pops X- & Y-coordinates on paint stack
- POPPAINT PROC NEAR
- MOV DI,[BP] ;Pop Y
- INC BP ; then increment stack
- INC BP
- MOV SI,[BP] ;Pop X
- INC BP
- INC BP
- RET
- POPPAINT ENDP
- ;
- ;Main PAINT routine
- PAINT PROC FAR
- ;
- ;Initialize paint color
- MOV DX,COLOR
- ;
- ;Initialize paint stack
- LEA BP,PAINT_STAK ;BP is set to top of stack
- CALL PUSHPAINT ;Push seed onto stack
- ;
- ;Main loop for painting
- PAINT1:
- LEA AX,PAINT_STAK ;Stack empty?
- CMP BP,AX
- JNE PAINT2 ;Continue, if not
- JMP PAINT_XIT ;Else exit
- ;
- ;Get the next place to paint
- PAINT2:
- CALL POPPAINT ;Pop the next place to paint
- CALL GET_COLOR ;Color is returned in AL
- CMP AL,DL ;Is it filled?
- JE PAINT1
- CMP AL,DH ;Is it boundary?
- JE PAINT1
- CMP DI,0 ;Top of screen?
- JL PAINT1
- CMP DI,199 ;Bottom of screen?
- JG PAINT1
- ;
- ;Move right until boundary is reached
- PAINT3:
- INC SI ;X <-- X + 1
- CALL GET_COLOR ;Look right
- DEC SI ;Restore X
- ;
- CMP AL,DL ;Is it filled?
- JE PAINT4
- CMP AL,DH ;Is it boundary color?
- JE PAINT4
- CMP SI,319 ;At right screen boundary?
- JE PAINT4
- INC SI ;X <-- X + 1
- JMP PAINT3
- ;
- ;Push above and below
- PAINT4:
- DEC DI ;Y <-- Y - 1
- CALL GET_COLOR ;Check above
- MOV BH,AL ;Save above state
- CMP AL,DL ;Is it filled?
- JE PAINT5
- CMP AL,DH ;Is it boundary color?
- JE PAINT5
- CALL PUSHPAINT ;Push above
- PAINT5:
- INC DI ;Restore Y
- INC DI ;Y <-- Y + 1
- CALL GET_COLOR ;Check below
- MOV BL,AL ;Save below state
- CMP AL,DL ;Is it filled?
- JE PAINT6
- CMP AL,DH ;Is it boundary color?
- JE PAINT6
- CALL PUSHPAINT ;Push below
- PAINT6:
- DEC DI ;Restore Y
- ;
- ;Anchor the end point of the scan line
- MOV X2,SI ;Store X-coord, end of scan lin
- MOV Y2,DI ;Store Y-coord, end of scan lin
- ;
- ;Plot as we scan left, checking above & below
- PAINT7:
- ;Check above
- DEC DI ;Y <-- Y - 1
- CALL GET_COLOR ;Check above
- CMP AL,DL ;Is it filled?
- JE PAINT9
- CMP AL,DH ;Is it boundary color?
- JE PAINT9
- ;
- CMP BH,DL ;Last above filled?
- JE PAINT8
- CMP BH,DH ;Was it boundary color?
- JE PAINT8
- JMP PAINT9
- PAINT8:
- CALL PUSHPAINT ;Push above if new place
- ; to paint
- PAINT9:
- MOV BH,AL ;Update last above
- ;
- INC DI ;Restore Y
- ;
- ;Check below
- INC DI ;Y <-- Y + 1
- CALL GET_COLOR ;Check below
- CMP AL,DL ;Is it filled?
- JE PAINT11
- CMP AL,DH ;Is it boundary color?
- JE PAINT11
- ;
- CMP BL,DL ;Last below filled?
- JE PAINT10
- CMP BL,DH ;Was it boundary color?
- JE PAINT10
- JMP PAINT11
- PAINT10:
- CALL PUSHPAINT ;Push below if new place
- ; to paint
- PAINT11:
- DEC DI
- MOV BL,AL ;Update last below
- ;
- INC DI ;Restore Y
- ;
- ;Move left
- DEC SI ;X <-- X - 1
- JL PAINT12 ;Stop the scan if too far left
- CALL GET_COLOR ;Check the point
- CMP AL,DL ;Is it filled yet?
- JE PAINT12 ; if so, next scan line
- CMP AL,DH ;Is it boundary yet?
- JE PAINT12 ; if so, next scan line
- JMP PAINT7 ;Continue painting scan line
- PAINT12:
- INC SI ;Restore X
- MOV X1,SI ;Store X-coordinate of start
- MOV Y1,DI ;Store Y-coordinate of start
- CALL SET_BOX ;Plot the scan line
- JMP PAINT1 ;Next place to paint
- ;
- PAINT_XIT:
- RET
- PAINT ENDP
- ;------------------------------------------------------------------------------
- CODES ENDS
- ;
- END
- ;______________________________________________________________________________
- ;>>>>> Physical EOF GRAPHICS.ASM <<<<<